<?php
require_once 'common.php';
require_once 'OaAppModel.php';
require_once 'OaAppServerModel.php';

/**
 * 订单模型
 * @author wangjiajun
 *
 */
class OaAppConfigOrderModel extends OpModel
{
    
    // 订单类型
    const CONFIG_ORDER_TYPE_JOIN = 1;                // 接入订单
    const CONFIG_ORDER_TYPE_MODIFY = 2;              // 修改订单
    const CONFIG_ORDER_TYPE_SERVER_CONFIG = 3;       // 区组配置订单
    
    // 订单状态
    const CONFIG_ORDER_STATUS_DEVELOPING = 1;        // 开发
    const CONFIG_ORDER_STATUS_TESTING = 2;           // 测评
    const CONFIG_ORDER_STATUS_CONFIGING = 3;         // 正式环境配置
    const CONFIG_ORDER_STATUS_APPLY_RELEASE = 4;     // 申请上线
    const CONFIG_ORDER_STATUS_AUDITING = 5;          // 审核
    const CONFIG_ORDER_STATUS_IN_OPERATION = 6;      // 运营
    
    // 任务类型
    const CONFIG_JOB_OPEN_LOGIN_SERVICE = 'open_login_service';         // 开通认证服务
    const CONFIG_JOB_MODIFY_LOGIN_SERVICE = 'modify_login_service';     // 修改认证服务
    const CONFIG_JOB_CLOSE_LOGIN_SERVICE = 'close_login_service';       // 关闭认证服务
    const CONFIG_JOB_OPEN_IBW_SERVICE = 'open_ibw_service';             // 开通圈圈（IBW）服务
    const CONFIG_JOB_MODIFY_IBW_SERVICE = 'modify_ibw_service';         // 修改圈圈（IBW）服务
    const CONFIG_JOB_CLOSE_IBW_SERVICE = 'close_ibw_service';           // 关闭圈圈（IBW）服务
    const CONFIG_JOB_OPEN_IGW_SERVICE = 'open_igw_service';             // 开通圈圈（IGW）服务
    const CONFIG_JOB_MODIFY_IGW_SERVICE = 'modify_igw_service';         // 修改圈圈（IGW）服务
    const CONFIG_JOB_CLOSE_IGW_SERVICE = 'close_igw_service';           // 关闭圈圈（IGW）服务
    const CONFIG_JOB_OPEN_PAY_SERVICE = 'open_pay_service';             // 开通支付服务
    const CONFIG_JOB_MODIFY_PAY_SERVICE = 'modify_pay_service';         // 修改支付服务
    const CONFIG_JOB_CLOSE_PAY_SERVICE = 'close_pay_service';           // 关闭支付服务
    const CONFIG_JOB_OPEN_BILLING_SERVICE = 'open_billing_service';     // 开通计费服务
    const CONFIG_JOB_MODIFY_BILLING_SERVICE = 'modify_billing_service'; // 修改计费服务
    const CONFIG_JOB_CLOSE_BILLING_SERVICE = 'close_billing_service';   // 关闭计费服务
    const CONFIG_JOB_OPEN_HELP_SERVICE = 'open_help_service';           // 开通彩虹服务
    const CONFIG_JOB_MODIFY_HELP_SERVICE = 'modify_help_service';       // 修改彩虹服务
    const CONFIG_JOB_CLOSE_HELP_SERVICE = 'close_help_service';         // 关闭彩虹服务
    const CONFIG_JOB_OPEN_BONUS_SERVICE = 'open_bonus_service';         // 开通分红服务
    const CONFIG_JOB_MODIFY_BONUS_SERVICE = 'modify_bonus_service';     // 修改分红服务
    const CONFIG_JOB_CLOSE_BONUS_SERVICE = 'close_bonus_service';       // 关闭分红服务
    const CONFIG_JOB_OPEN_POINTS_SERVICE = 'open_points_service';       // 开通积分服务
    const CONFIG_JOB_MODIFY_POINTS_SERVICE = 'modify_points_service';   // 修改积分服务
    const CONFIG_JOB_CLOSE_POINTS_SERVICE = 'close_points_service';     // 关闭积分服务
    const CONFIG_JOB_OPEN_PREVENT_OBSESSION_SERVICE = 'open_prevent_obsession_service';     // 开通防沉迷服务
    const CONFIG_JOB_MODIFY_PREVENT_OBSESSION_SERVICE = 'modify_prevent_obsession_service'; // 修改防沉迷服务
    const CONFIG_JOB_CLOSE_PREVENT_OBSESSION_SERVICE = 'close_prevent_obsession_service';   // 关闭防沉迷服务
    const CONFIG_JOB_MODIFY_BASIC_INFO = 'modify_basic_info';           // 修改基本信息
    const CONFIG_JOB_MODIFY_APP_PUB_KEY = 'modify_app_pub_key';         // 修改应用公钥
    
    // 任务状态
    const CONFIG_TASK_STATUS_INVALID = 0;           // 未选择
    const CONFIG_TASK_STATUS_VALID = 1;             // 已选择
    const CONFIG_TASK_STATUS_FINISHED_OK = 2;       // 完成成功
    const CONFIG_TASK_STATUS_FINISHED_FAIL = 3;     // 完成失败
    const CONFIG_TASK_STATUS_CLOSE = 4;     		// 完成后又取消
    
    // 任务环境
    const CONFIG_TASK_ENV_TEST = 1;            // 测试环境
    const CONFIG_TASK_ENV_PRODUCTION = 2;      // 正式环境
    
    // 后台开通服务请求状态
    const BG_OPEN_SERVICE_STATUS_SUBMITTED = 0;            // 等待处理
    const BG_OPEN_SERVICE_STATUS_FINISHED_OK = 1;          // 开通成功
    const BG_OPEN_SERVICE_STATUS_FINISHED_FAIL = 2;        // 开通失败
    
    // 应用同步状态
    const APP_SYNC_STATUS_NO = 0;                // 尚未同步
    const APP_SYNC_STATUS_TEST = 1;              // 已同步连调环境
    const APP_SYNC_STATUS_PRODUCTION = 2;        // 已同步正式环境
    
    //SDG是否审核通过, 1通过，2未通过
    const APP_SDG_AGREE = 1;	
    const APP_SDG_NOT_AGREE = 2;
    
    public static $configJobs = array(
        self::CONFIG_JOB_OPEN_LOGIN_SERVICE => array(
            'service_name' => '认证功能',
            'description' => '开通认证服务'
        ),
        self::CONFIG_JOB_MODIFY_LOGIN_SERVICE => array(
            'service_name' => '认证功能',
            'description' => '修改认证服务'
        ),
        self::CONFIG_JOB_CLOSE_LOGIN_SERVICE => array(
            'service_name' => '认证功能',
            'description' => '关闭认证服务'
        ),
        self::CONFIG_JOB_OPEN_IBW_SERVICE => array(
            'service_name' => '圈 圈',
            'description' => '开通圈圈（IBW）服务'
        ),
        self::CONFIG_JOB_MODIFY_IBW_SERVICE => array(
            'service_name' => '圈 圈',
            'description' => '修改圈圈（IBW）服务'
        ),
        self::CONFIG_JOB_CLOSE_IBW_SERVICE => array(
            'service_name' => '圈 圈',
            'description' => '关闭圈圈（IBW）服务'
        ),
        self::CONFIG_JOB_OPEN_IGW_SERVICE => array(
            'service_name' => '圈 圈',
            'description' => '开通圈圈（IGW）服务'
        ),
        self::CONFIG_JOB_MODIFY_IGW_SERVICE => array(
            'service_name' => '圈 圈',
            'description' => '修改圈圈（IGW）服务'
        ),
        self::CONFIG_JOB_CLOSE_IGW_SERVICE => array(
            'service_name' => '圈 圈',
            'description' => '关闭圈圈（IGW）服务'
        ),
        self::CONFIG_JOB_OPEN_PAY_SERVICE => array(
            'service_name' => '支付服务',
            'description' => '开通支付服务'
        ),
        self::CONFIG_JOB_MODIFY_PAY_SERVICE => array(
            'service_name' => '支付服务',
            'description' => '修改支付服务'
        ),
        self::CONFIG_JOB_CLOSE_PAY_SERVICE => array(
            'service_name' => '支付服务',
            'description' => '关闭支付服务'
        ),
        self::CONFIG_JOB_OPEN_BILLING_SERVICE => array(
            'service_name' => '计费服务',
            'description' => '开通计费服务'
        ),
        self::CONFIG_JOB_MODIFY_BILLING_SERVICE => array(
            'service_name' => '计费服务',
            'description' => '修改计费服务'
        ),
        self::CONFIG_JOB_CLOSE_BILLING_SERVICE => array(
            'service_name' => '计费服务',
            'description' => '关闭计费服务'
        ),
        self::CONFIG_JOB_OPEN_HELP_SERVICE => array(
            'service_name' => '彩虹服务',
            'description' => '开通彩虹服务'
        ),
        self::CONFIG_JOB_MODIFY_HELP_SERVICE => array(
            'service_name' => '彩虹服务',
            'description' => '修改彩虹服务'
        ),
        self::CONFIG_JOB_CLOSE_HELP_SERVICE => array(
            'service_name' => '彩虹服务',
            'description' => '关闭彩虹服务'
        ),
        self::CONFIG_JOB_OPEN_BONUS_SERVICE => array(
            'service_name' => '盛大分红',
            'description' => '开通分红服务'
        ),
        self::CONFIG_JOB_MODIFY_BONUS_SERVICE => array(
            'service_name' => '盛大分红',
            'description' => '修改分红服务'
        ),
        self::CONFIG_JOB_CLOSE_BONUS_SERVICE => array(
            'service_name' => '盛大分红',
            'description' => '关闭分红服务'
        ),
        self::CONFIG_JOB_OPEN_POINTS_SERVICE => array(
            'service_name' => '积分服务',
            'description' => '开通积分服务'
        ),
        self::CONFIG_JOB_MODIFY_POINTS_SERVICE => array(
            'service_name' => '积分服务',
            'description' => '修改积分服务'
        ),
        self::CONFIG_JOB_CLOSE_POINTS_SERVICE => array(
            'service_name' => '积分服务',
            'description' => '关闭积分服务'
        ),
        self::CONFIG_JOB_OPEN_PREVENT_OBSESSION_SERVICE => array(
            'service_name' => '防沉迷服务',
            'description' => '开通防沉迷服务'
        ),
        self::CONFIG_JOB_MODIFY_PREVENT_OBSESSION_SERVICE => array(
            'service_name' => '防沉迷服务',
            'description' => '修改防沉迷服务'
        ),
        self::CONFIG_JOB_CLOSE_PREVENT_OBSESSION_SERVICE => array(
            'service_name' => '防沉迷服务',
            'description' => '关闭防沉迷服务'
        ),
        self::CONFIG_JOB_MODIFY_BASIC_INFO => array(
            'service_name' => '',
            'description' => '修改基本信息'
        ),
        self::CONFIG_JOB_MODIFY_APP_PUB_KEY => array(
            'service_name' => '',
            'description' => '修改应用公钥'
        )
    );
    
    private $_oaWebDb;
    private $_appConfigOrderTable;
    private $_appConfigTaskTable;
    private $_appSnapshotTable;
    private $_bgOpenServiceReqTable;
    
    public static function getConstantValueByName($name, $default = 0)
    {
        return self::_getConstByName($name, '', $default, 'OaAppConfigOrderModel');
    }
    
    public function __construct($logger = null)
    {
        if (is_null($logger)) {
            $logger = getOaModelLogger();
        }
        parent::__construct($logger);
        $dbConfig = Oa_Util_Config::getSingleDbConfig(OA_WEB_DB_CLUSTER_ID);
        $db = OpDbModel::getInstance($dbConfig, $logger);
        $this->_oaWebDb = $db;
        $this->_appConfigOrderTable = new OpTableModel($db, 'app_config_order', $logger);
        $this->_appConfigTaskTable = new OpTableModel($db, 'app_config_task', $logger);
        $this->_appSnapshotTable = new OpTableModel($db, 'app_snapshot', $logger);
        $this->_bgOpenServiceReqTable = new OpTableModel($db, 'bg_open_service_request', $logger);
    }
    
    /**
     * 新建订单，一个应用同时只能有一个未处理完的订单
     * @param string $orderId 订单ID，工作流返回
     * @param int $appId
     * @param int $creator
     * @param array $row
     * @return int|boolean 如果存在尚未处理完的订单，设置错误号1
     */
    public function createConfigOrder($orderId, $appId, $creator, $row = array())
    {
        $result = $this->getAppCurrentConfigOrder($appId);
        if ($result === false) {
            $this->_logger->err("get app current config order failed");
            return false;
        }
        if (!is_null($result)) {
            $this->_logger->err("app has a unfinished order");
            $this->_setError(1);
            return false;
        }
        $row = array_merge(array(
            'id' => $orderId,
            'app_id' => $appId,
            'status' => self::CONFIG_ORDER_STATUS_DEVELOPING,
            'creator' => $creator,
            'create_time' => date('Y-m-d H:i:s')
        ), $row);
        if (!$this->_appConfigOrderTable->insert($row, null, false)) {
        	$this->_logger->err("insert failed");
        	return false;
        }
        // 生成快照，用于保存同步后的信息
        if (!$this->addAppSnapshot($orderId)) {
        	$this->deleteConfigOrder($orderId);
        	$this->_logger->err("add snapshot failed: order-$orderId");
        	return false;
        }
        return true;
    }
    
    /**
     * 查询订单
     * @param string $orderId
     * @param array $columns
     * @return array|null|boolean
     */
    public function getConfigOrder($orderId, $columns = null)
    {
        $order = $this->_appConfigOrderTable->getRow(array(
            'id' => $orderId
        ), null, $columns);
        if ($order === false) {
            $this->_logger->err("get row failed");
            return false;
        }
        return $order;
    }
    
    /**
     * 查询多个订单
     * @param array $orderIds
     * @return array|boolean
     */
    public function getConfigOrderMulti($orderIds)
    {
    	if (empty($orderIds)) {
    		return array();
    	}
    	$orderIds = escapeInput($orderIds);
    	$sql = "SELECT * FROM app_config_order WHERE id IN (" . implode(',', $orderIds) . ")";
    	$orders = $this->_oaWebDb->query($sql);
    	if ($orders === false) {
    		return false;
    	}
    	$result = array();
    	foreach ($orders as $order) {
    		$result[$order['id']] = $order;
    	}
    	return $result;
    }
    
    /**
     * 查询订单状态
     * @param int $orderId
     * @return int|boolean
     */
    public function getConfigOrderStatus($orderId)
    {
        $order = $this->getConfigOrder($orderId, array('status'));
        if ($order === false) {
            $this->_logger->err("get config order failed");
            return false;
        }
        if (is_array($order)) {
            return $order['status'];
        } else {
            return false;
        }
    }
    
    /**
     * 根据指定条件查询订单列表
     * @param array $where
     * @param int $offset
     * @param int $count
     * @param string $sort
     * @param array $otherWhere
     * @return array|boolean
     */
    public function getConfigOrderList($where = null, $offset = 0, $count = null, 
        $sort = null, $otherWhere = null)
    {
        $sql = "SELECT * FROM app_config_order" . getSqlCond($where, $offset, $count, $sort, 
            $otherWhere);
        $result = $this->_appConfigOrderTable->query($sql);
        if ($result === false) {
            $this->_logger->err("query failed");
            return false;
        }
        return $result;
    }
    
    /**
     * 根据指定条件查询订单总数
     * @param array $where
     * @param array $otherWhere
     * @return int|boolean
     */
    public function getConfigOrderListCount($where = null, $otherWhere = null)
    {
        $sql = "SELECT COUNT(*) FROM app_config_order" . getSqlCond($where, 0, 0, null, 
            $otherWhere);
        $result = $this->_appConfigOrderTable->query($sql, PDO::FETCH_NUM);
        if ($result === false) {
            $this->_logger->err("query failed");
            return false;
        }
        return (int) $result[0][0];
    }
    
    /**
     * 查询应用订单列表
     * @param int $appId
     * @param int $offset
     * @param int $count
     * @return array|boolean
     */
    public function getAppConfigOrders($appId, $offset = 0, $count = null)
    {
        return $this->getConfigOrderList(array(
            'app_id' => $appId
        ), $offset, $count, 'create_time DESC');
    }
    
    /**
     * 修改订单
     * @param string $orderId
     * @param array $row
     * @return boolean 如果订单不存在，设置错误号1
     */
    public function modifyConfigOrder($orderId, $row)
    {
        $order = $this->getConfigOrder($orderId);
        if (!is_array($order)) {
            $this->_setError(1, "order not exists");
            return false;
        }
        $result = $this->_appConfigOrderTable->update(array(
            'id' => $orderId
        ), $row);
        // 如果订单结束，更新订单快照里的基本信息
        if ($result && isset($row['status']) && 
            $row['status'] == OaAppModel::APP_STATUS_IN_OPERATION) {
            $env = OaAppModel::APP_CONFIG_ENV_TEST;
        	if (!$this->updateAppSnapshot($orderId, $env, 'basic_info')) {
        		$this->_logger->warning("update snapshot failed: order-$orderId, " . 
        			"env-$env, column-basic_info");
        	}
            $env = OaAppModel::APP_CONFIG_ENV_PRODUCTION;
        	if (!$this->updateAppSnapshot($orderId, $env, 'basic_info')) {
        		$this->_logger->warning("update snapshot failed: order-$orderId, " . 
        			"env-$env, column-basic_info");
        	}
        }
        return $result;
    }
    
    /**
     * 设置订单状态
     * @param string $orderId
     * @param int $status
     * @param string $notes
     * @return boolean
     */
    public function setConfigOrderStatus($orderId, $status, $notes = '')
    {        
        return $this->modifyConfigOrder($orderId, array(
        	'status' => $status,
            'notes' => $notes
        ));
    }
    
    /**
     * 设置应用基本信息同步状态
     * @param string $orderId
     * @param int $status
     * @return boolean
     */
    public function setAppInfoSyncStatus($orderId, $status)
    {
        return $this->modifyConfigOrder($orderId, array(
        	'app_info_sync_status' => $status
        ));
    }
    
    /**
     * 查询应用基本信息同步状态
     * @param string $orderId
     * @return int|boolean
     */
    public function getAppInfoSyncStatus($orderId)
    {
        $order = $this->getConfigOrder($orderId);
        if (is_array($order)) {
            return $order['app_info_sync_status'];
        } else {
            return false;
        }
    }
    
    /**
     * 设置应用公钥同步状态
     * @param string $orderId
     * @param int $status
     * @return boolean
     */
    public function setAppPubKeySyncStatus($orderId, $status)
    {
        return $this->modifyConfigOrder($orderId, array(
        	'app_pub_key_sync_status' => $status
        ));
    }
    
    /**
     * 查询应用公钥同步状态
     * @param string $orderId
     * @return int|boolean
     */
    public function getAppPubKeySyncStatus($orderId)
    {
        $order = $this->getConfigOrder($orderId);
        if (is_array($order)) {
            return $order['app_pub_key_sync_status'];
        } else {
            return false;
        }
    }
    
    /**
     * 设置应用服务器配置同步状态
     * @param string $orderId
     * @param int $status
     * @return boolean
     */
    public function setAppServerConfigSyncStatus($orderId, $status)
    {
        return $this->modifyConfigOrder($orderId, array(
        	'app_server_config_sync_status' => $status
        ));
    }
    
    /**
     * 查询应用服务器配置同步状态
     * @param string $orderId
     * @return int|boolean
     */
    public function getAppServerConfigSyncStatus($orderId)
    {
        $order = $this->getConfigOrder($orderId);
        if (is_array($order)) {
            return $order['app_server_config_sync_status'];
        } else {
            return false;
        }
    }
    
    /**
     * 删除订单
     * @param string $orderId
     * @return boolean
     */
    public function deleteConfigOrder($orderId)
    {
        if ($this->deleteConfigOrderTasks($orderId) === false) {
            $this->_logger->err("delete config order tasks failed");
            return false;
        }
        return $this->_appConfigOrderTable->delete(array(
            'id' => $orderId
        ));
    }
    
    /**
     * 删除应用的所有订单
     * @param int $appId
     * @return boolean
     */
    public function deleteAppConfigOrders($appId)
    {
        $orders = $this->getAppConfigOrders($appId);
        if ($orders === false) {
            $this->_logger->err("get app config orders failed");
            return false;
        }
        foreach ($orders as $order) {
            if ($this->deleteConfigOrderTasks($order['id']) === false) {
                $this->_logger->err("delete config order tasks failed");
                return false;
            }
        }
        return $this->_appConfigOrderTable->delete(array(
            'app_id' => $appId
        ));
    }
    
    /**
     * 查询当前订单（尚未完成），没有则返回null
     * @param int $appId
     * @return array|null|boolean
     */
    public function getAppCurrentConfigOrder($appId)
    {
        $result = $this->getConfigOrderList(array(
            'app_id' => $appId
        ), 0, 1, 'create_time DESC', array(
            array(
                'key' => 'status',
                'operation' => '!=',
                'value' => self::CONFIG_ORDER_STATUS_IN_OPERATION
            )
        ));
        if ($result === false) {
            $this->_logger->err("get config order multi failed");
            return false;
        }
        return $result ? $result[0] : null;
    }
    
    /**
     * 查询最后一个订单，没有则返回null
     * @param int $appId
     * @return array|null|boolean
     */
    public function getAppLastConfigOrder($appId)
    {
        $result = $this->getConfigOrderList(array(
            'app_id' => $appId
        ), 0, 1, 'create_time DESC');
        if ($result === false) {
            $this->_logger->err("get config order multi failed");
            return false;
        }
        return $result ? $result[0] : null;
    }
    
    /**
     * 给订单增加一个任务
     * @param string $orderId
     * @param string $jobName
     * @param mixed $data
     * @param int $env 哪个环境
     * @param array $row
     * @return int|boolean
     */
    public function createConfigTask($orderId, $jobName, $data = null, $env = self::CONFIG_TASK_ENV_TEST, 
        $row = array())
    {
        if (!in_array($jobName, array_keys(self::$configJobs))) {
            $this->_logger->err("unknown job");
            return false;
        }
        $row = array_merge(array(
            'order_id' => $orderId,
            'environment' => $env,
            'job_name' => $jobName,
            'data' => json_encode($data),
            'status' => self::CONFIG_TASK_STATUS_VALID,
            'create_time' => date('Y-m-d H:i:s')
        ), $row);
        return $this->_appConfigTaskTable->insert($row);
    }
    
    /**
     * 查询任务
     * @param string $taskId
     * @param array $columns
     * @return array|null|boolean
     */
    public function getConfigTask($taskId, $columns = null)
    {
        $result = $this->_appConfigTaskTable->getRow(array(
            'id' => $taskId
        ), null, $columns);
        if ($result === false) {
            $this->_logger->err("get row failed");
            return false;
        }
        if (is_array($result)) {
            $result['data'] = json_decode($result['data'], true);
            $result['job_description'] = self::$configJobs[$result['job_name']]['description'];
        }
        return $result;
    }
    
    /**
     * 查询订单包含的所有任务，返回数组以任务名为key
     * @param string $orderId
     * @param int $env 哪个环境
     * @param array $columns
     * @return array
     */
    public function getConfigOrderTasks($orderId, $env = self::CONFIG_TASK_ENV_TEST, $columns = null)
    {
        $tasks = $this->_appConfigTaskTable->get(array(
            'order_id' => $orderId,
            'environment' => $env
        ), 0, null, null, null, $columns);
        $result = array();
        foreach ($tasks as $task) {
            $task['data'] = json_decode($task['data'], true);
            $task['job_description'] = self::$configJobs[$task['job_name']]['description'];
            $result[] = $task;
        }
        return $result;
    }
    
    /**
     * 查询某个订单里跟某服务相关的任务
     * @param string $orderId
     * @param string $service
     * @param int $env
     */
    public function getConfigOrderTasksOfService($orderId, $service, 
    	$env = self::CONFIG_TASK_ENV_TEST)
    {
        $tasks = $this->getConfigOrderTasks($orderId, $env);
        $result = array();
        foreach ($tasks as $task) {
        	if (preg_match("/_{$service}_service$/", $task['job_name'])) {
        		$result[] = $task;
        	}
        }
        return $result;
    }
    
    /**
     * 修改任务
     * @param int $taskId
     * @param array $row
     * @return boolean
     */
    public function modifyConfigTask($taskId, $row)
    {
        return $this->_appConfigTaskTable->update(array(
            'id' => $taskId
        ), $row);
    }
    
    /**
     * 删除任务
     * @param int $taskId
     * @return boolean
     */
    public function deleteConfigTask($taskId)
    {
        return $this->_appConfigTaskTable->delete(array(
            'id' => $taskId
        ));
    }
    
    /**
     * 删除订单下的所有任务
     * @param int $orderId
     * @param int $env 哪个环境
     * @return boolean
     */
    public function deleteConfigOrderTasks($orderId, $env = self::CONFIG_TASK_ENV_TEST)
    {
        return $this->_appConfigTaskTable->delete(array(
            'order_id' => $orderId,
            'environment' => $env
        ));
    }
    
    /**
     * 查询任务，没有则返回null
     * @param string $orderId
     * @param string $jobName
     * @param int $env 哪个环境
     * @return array|null|boolean 
     */
    public function getConfigOrderTaskByJobName($orderId, $jobName, $env = self::CONFIG_TASK_ENV_TEST)
    {
        $task = $this->_appConfigTaskTable->getRow(array(
            'order_id' => $orderId,
            'job_name' => $jobName,
            'environment' => $env
        ));
        if (is_array($task)) {
            $task['data'] = json_decode($task['data'], true);
            $task['job_description'] = self::$configJobs[$task['job_name']]['description'];
        }
        return $task;
    }
    
    /**
     * 查询任务状态
     * @param string $orderId
     * @param string $jobName
     * @param int $env 哪个环境
     * @return int
     */
    public function getConfigTaskStatusByJobName($orderId, $jobName, $env = self::CONFIG_TASK_ENV_TEST)
    {
        $task = $this->getConfigOrderTaskByJobName($orderId, $jobName, $env);
        if (is_array($task)) {
            return $task['status'];
        } else {
            return false;
        }
    }
    
	/**
     * 修改任务
     * @param string $orderId
     * @param string $jobName
     * @param array $row
     * @param int $env 哪个环境
     * @return boolean
     */
    public function modifyConfigTaskByJobName($orderId, $jobName, $row, $env = self::CONFIG_TASK_ENV_TEST)
    {
        return $this->_appConfigTaskTable->update(array(
            'order_id' => $orderId,
            'job_name' => $jobName,
            'environment' => $env
        ), $row);
    }
    
    /**
     * 修改任务配置数据
     * @param string $orderId
     * @param string $jobName
     * @param mixed $data
     * @param int $env 哪个环境
     * @return boolean
     */
    public function modifyConfigTaskDataByJobName($orderId, $jobName, $data, $env = self::CONFIG_TASK_ENV_TEST)
    {
        return $this->modifyConfigTaskByJobName($orderId, $jobName, array(
            'data' => json_encode($data)
        ), $env);
    }
    
    /**
     * 修改任务状态
     * @param string $orderId
     * @param string $jobName
     * @param int $status
     * @param string $notes 备注
     * @param int $env 哪个环境
     * @return boolean
     */
    public function modifyConfigTaskStatusByJobName($orderId, $jobName, $status, $notes = '', $env = self::CONFIG_TASK_ENV_TEST)
    {
        return $this->modifyConfigTaskByJobName($orderId, $jobName, array(
            'status' => $status,
            'notes' => $notes
        ), $env);
    }
    
    /**
     * 删除任务
     * @param string $orderId
     * @param string $jobName
     * @param int $env
     * @return boolean
     */
    public function deleteConfigTaskByJobName($orderId, $jobName, $env = self::CONFIG_TASK_ENV_TEST)
    {
        return $this->_appConfigTaskTable->delete(array(
            'order_id' => $orderId,
            'job_name' => $jobName,
            'environment' => $env
        ));
    }
    
    /**
     * 增加一个后台开通服务请求
     * @param string $orderId
     * @param int $env 在哪个环境开通
     * @param int $intervalSeconds 同一个订单两次请求的最小间隔时间
     * @return int|boolean 如果距上次请求的间隔小于指定时间，设置错误号1
     */
    public function addOpenServiceRequest($orderId, $env = self::CONFIG_TASK_ENV_TEST, $intervalSeconds = 10)
    {
        $rows = $this->getOpenServiceRequestList(array(
            'order_id' => $orderId
        ), 0, 1, 'create_time DESC');
        if ($rows) {
            $date = new Date($rows[0]['create_time']);
            if ((time() - $date->getTime()) < $intervalSeconds) {
                $this->_setError(1, "request too often");
                return false;
            }
        }
        return $this->_bgOpenServiceReqTable->insert(array(
            'order_id' => $orderId,
            'environment' => $env,
            'create_time' => date('Y-m-d H:i:s')
        ));
    }
    
    /**
     * 查询某个后台开通服务请求
     * @param int $id
     * @return array|null|boolean
     */
    public function getOpenServiceRequest($id)
    {
        return $this->_bgOpenServiceReqTable->getRow(array(
            'id' => $id
        ));
    }
    
    /**
     * 查询后台开通服务请求列表
     * @param array $where
     * @param int $offset
     * @param int $count
     * @param string $sort
     * @param array $otherWhere
     * @return array|boolean
     */
    public function getOpenServiceRequestList($where, $offset = 0, $count = null, 
        $sort = null, $otherWhere = null)
    {
        return $this->_bgOpenServiceReqTable->get($where, $offset, $count, $sort, $otherWhere);
    }
        
    /**
     * 查询后台开通服务请求数
     * @param array $where
     * @param array $otherWhere
     * @return int|boolean
     */
    public function getOpenServiceRequestListCount($where, $otherWhere = null)
    {
        return $this->_bgOpenServiceReqTable->getCount($where, $otherWhere);
    }
    
    /**
     * 根据请求状态查询后台开通服务请求列表
     * @param int $status
     * @param int $offset
     * @param int $count
     * @return array|boolean
     */
    public function getOpenServiceRequestsByStatus($status = self::BG_OPEN_SERVICE_STATUS_SUBMITTED, 
        $offset = 0, $count = null)
    {
        return $this->getOpenServiceRequestList(array(
            'status' => $status
        ), $offset, $count, 'create_time DESC');
    }
    
    /**
     * 设置后台开通服务请求的状态
     * @param int $id 请求ID
     * @param int $status
     * @return boolean
     */
    public function setOpenServiceRequestStatus($id, $status)
    {
        return $this->_bgOpenServiceReqTable->update(array(
            'id' => $id
        ), array(
            'status' => $status
        ));
    }
    
    /**
     * 后台开通服务请求的尝试次数加1
     * @param int $id 请求ID
     * @return boolean
     */
    public function incOpenServiceRequestTryTimes($id)
    {
        return $this->_bgOpenServiceReqTable->update(array(
            'id' => $id
        ), null, array(
            'try_times' => 'try_times+1'
        ));
    }
    
    /**
     * 生成应用快照
     * @param string $orderId
     * @param int $env 默认为null，同时生成连调和运营两份快照
     * @return boolean
     */
    public function addAppSnapshot($orderId, $env = null)
    {
        $order = $this->getConfigOrder($orderId);
        if (!is_array($order)) {
            $this->_logger->err("order not exists: order-$orderId");
            return false;
        }        
        $appId = $order['app_id'];
        if (is_null($env)) {
        	$envs = array(OaAppModel::APP_CONFIG_ENV_TEST, OaAppModel::APP_CONFIG_ENV_PRODUCTION);
        } else {
        	if (!in_array($env, array(OaAppModel::APP_CONFIG_ENV_TEST, 
        		OaAppModel::APP_CONFIG_ENV_PRODUCTION))) {
        		$this->_logger->err("env is invalid: env-$env");
        		return false;
        	}
        	$envs = array($env);
        }
        foreach ($envs as $env) {
            if (is_array($this->getAppSnapshot($orderId, $env, array('basic_info')))) {
                $this->_logger->err("snapshot already exists: order-$orderId");
                return false;
            }
            $appModel = new OaAppModel($env, $this->_logger);
            $appServerModel = new OaAppServerModel($env, $this->_logger);
            $basicInfo = $appModel->getApp($appId);
            $areaInfo = $appServerModel->getAppAreas($appId);
            $groupInfo = $appServerModel->getAppGroups($appId);
            $serverInfo = $appServerModel->getAppServers($appId);
            $loginServerInfo = $appServerModel->getAppLoginServers($appId);
            $loginServerValidInfo = $appServerModel->getAppLoginServerValidTos($appId);
            $payServerInfo = $appServerModel->getAppPayServers($appId);
            $payServerValidInfo = $appServerModel->getAppPayServerValidTos($appId);
            if (!$this->_appSnapshotTable->insert(array(
                'order_id' => $orderId,
                'environment' => $env,
                'app_id' => $appId,
                'basic_info' => json_encode($basicInfo),
                'area_info' => json_encode($areaInfo),
                'group_info' => json_encode($groupInfo),
                'server_info' => json_encode($serverInfo),
                'login_server_info' => json_encode($loginServerInfo),
                'login_server_valid_info' => json_encode($loginServerValidInfo),
                'pay_server_info' => json_encode($payServerInfo),
                'pay_server_valid_info' => json_encode($payServerValidInfo),
                'create_time' => date('Y-m-d H:i:s')
            ), null, false)) {
                $this->_logger->err("add snapshot failed");
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 更新应用快照
     * @param string $orderId
     * @param int $env
     * @param string $column
     * @return boolean
     */
    public function updateAppSnapshot($orderId, $env, $column)
    {
        $order = $this->getConfigOrder($orderId);
        if (!is_array($order)) {
            $this->_logger->err("order not exists: order-$orderId");
            return false;
        }        
        $appId = $order['app_id'];
        $appModel = new OaAppModel($env, $this->_logger);
        $appServerModel = new OaAppServerModel($env, $this->_logger);
    	if ($column == 'basic_info') {
    		$data = $appModel->getApp($appId);
    	} else if ($column == 'area_info') {
    		$data = $appServerModel->getAppAreas($appId);
    	} else if ($column == 'group_info') {
            $data = $appServerModel->getAppGroups($appId);
    	} else if ($column == 'server_info') {
            $data = $appServerModel->getAppServers($appId);
    	} else if ($column == 'login_server_info') {
            $data = $appServerModel->getAppLoginServers($appId);
    	} else if ($column == 'login_server_valid_info') {
            $data = $appServerModel->getAppLoginServerValidTos($appId);
    	} else if ($column == 'pay_server_info') {
            $data = $appServerModel->getAppPayServers($appId);
    	} else if ($column == 'pay_server_valid_info') {
            $data = $appServerModel->getAppPayServerValidTos($appId);
    	} else {
    		$this->_logger->err("unknown column: column-$column");
    		return false;
    	}
        return $this->_appSnapshotTable->update(array(
        	'order_id' => $orderId, 
        	'environment' => $env
        ), array(
            $column => json_encode($data)
        ));
    }
    
    /**
     * 查询应用快照
     * @param string $orderId
     * @param int $env
     * @param array $columns
     * @return array|null|boolean
     */
    public function getAppSnapshot($orderId, $env, $columns = null)
    {
        if (is_null($columns)) {
            $columns = array('basic_info', 'area_info', 'group_info', 'server_info', 
            	'login_server_info', 'login_server_valid_info', 'pay_server_info', 
                'pay_server_valid_info'
            );
        }
        $snapshot = $this->_appSnapshotTable->getRow(array(
            'order_id' => $orderId,
            'environment' => $env
        ), null, $columns);
        if (is_array($snapshot)) {
            if (isset($snapshot['basic_info'])) {
                $snapshot['basic_info'] = json_decode($snapshot['basic_info'], true);
            }
            if (isset($snapshot['area_info'])) {
                $snapshot['area_info'] = json_decode($snapshot['area_info'], true);
            }
            if (isset($snapshot['group_info'])) {
                $snapshot['group_info'] = json_decode($snapshot['group_info'], true);
            }
            if (isset($snapshot['server_info'])) {
                $snapshot['server_info'] = json_decode($snapshot['server_info'], true);
            }
            if (isset($snapshot['login_server_info'])) {
                $snapshot['login_server_info'] = json_decode($snapshot['login_server_info'], true);
            }
            if (isset($snapshot['login_server_valid_info'])) {
                $snapshot['login_server_valid_info'] = json_decode($snapshot['login_server_valid_info'], true);
            }
            if (isset($snapshot['pay_server_info'])) {
                $snapshot['pay_server_info'] = json_decode($snapshot['pay_server_info'], true);
            }
            if (isset($snapshot['pay_server_valid_info'])) {
                $snapshot['pay_server_valid_info'] = json_decode($snapshot['pay_server_valid_info'], true);
            }
        }
        return $snapshot;
    }

    /**
     * 删除应用快照
     * @param string $orderId
     * @param int $env 默认为null，同时删除连调和运营两份快照
     * @return boolean
     */
    public function deleteAppSnapshot($orderId, $env = null)
    {
        if (is_null($env)) {
        	$envs = array(OaAppModel::APP_CONFIG_ENV_TEST, OaAppModel::APP_CONFIG_ENV_PRODUCTION);
        } else {
        	if (!in_array($env, array(OaAppModel::APP_CONFIG_ENV_TEST, 
        		OaAppModel::APP_CONFIG_ENV_PRODUCTION))) {
        		$this->_logger->err("env is invalid: env-$env");
        		return false;
        	}
        	$envs = array($env);
        }
        foreach ($envs as $env) {
        	if (!$this->_appSnapshotTable->delete(array(
	            'order_id' => $orderId,
        		'environment' => $env
	        ))) {
        		$this->_logger->err("delete failed: order-$orderId, env-$env");
        		return false;
        	}
        }
        return true;
    }
}
